#define _CRT_SECURE_NO_WARNINGS
#include<easyx.h>
#include<time.h>
#include<stdlib.h>
#include<windows.h>
#include<stdio.h>
#include<mmsystem.h>

#include<iostream>
using namespace std;

#include"Snake.h"
#include"fruit.h"
#include"definition.h"
#include"game_scene.h"

#pragma comment(lib,"MSIMG32.LIB")
#pragma comment(lib,"winmm.lib")

GameScene gamescene;

Head snakehead((GameSceneBoundaryRight+GameSceneBoundaryLeft)/2/GridSize,(GameSceneBoundaryTop+GameSceneBoundaryBottom)/2/GridSize);
Body snakebody(BodyMaxLength, (GameSceneBoundaryRight + GameSceneBoundaryLeft) / 2 / GridSize, (GameSceneBoundaryTop + GameSceneBoundaryBottom) / 2 / GridSize, (GameSceneBoundaryRight + GameSceneBoundaryLeft) / 2 / GridSize - 1, (GameSceneBoundaryTop + GameSceneBoundaryBottom) / 2 / GridSize);
Fruit fruit;

Scene currentscene = Scene::MainMenu;
Button currentbuttonstate = Button::Unactive;
Button currentexitbuttonstate = Button::Unactive;

FILE* ScoreRecord;

IMAGE MainMenuBackground;
IMAGE ButtonUnactive;
IMAGE ButtonActive;
IMAGE ExitButtonUnactive;
IMAGE ExitButtonActive;
IMAGE Apple;
IMAGE Speeding;

void ChangeDirection(ExMessage& msg);
bool CheckAlive();
void TriggerButton(ExMessage& msg);
void DrawButton();
void ResetGame();
int ReadScore();

int main()
{
	highest_score = ReadScore();
	mciSendString(_T("open music/bgm.mp3 alias bgm"), NULL, 0, NULL);

	loadimage(&MainMenuBackground, _T("image/mainmenu/background.png"));
	loadimage(&ButtonUnactive, _T("image/mainmenu/button_unactive.png"),ButtonWidth,ButtonHeight);
	loadimage(&ButtonActive, _T("image/mainmenu/button_active.png"),ButtonWidth,ButtonHeight);
	loadimage(&ExitButtonUnactive, _T("image/mainmenu/exit_button_unacntive.png"), ExitButtonWidth, ExitButtonHeight);
	loadimage(&ExitButtonActive, _T("image/mainmenu/exit_button_active.png"), ExitButtonWidth, ExitButtonHeight);
	loadimage(&Apple, _T("image/object/apple.png"), GridSize-2, GridSize-2);
	loadimage(&Speeding, _T("image/object/speeding.png"),20,20);

	ExMessage msg;

	//Create Gragh
	initgraph(WindowHeight, WindowWidth);
	SetWindowPos(GetHWnd(), HWND_TOPMOST,(GetSystemMetrics(SM_CXSCREEN) - WindowWidth) / 2, (GetSystemMetrics(SM_CYSCREEN) - WindowHeight) / 2, 0, 0, SWP_NOSIZE);

	BeginBatchDraw();

	while (RunningState)
	{
		switch (currentscene)
		{
		case Scene::MainMenu:
			while (peekmessage(&msg))
			{
				TriggerButton(msg);
			}
			cleardevice();
			putimage(0, 0, &MainMenuBackground);
			DrawButton();
			FlushBatchDraw();
			break;

		case Scene::GameScene:
			if (Reset)
			{
				ResetGame();
				Reset = false;
			}
			if (Playbgm)
			{
				mciSendString(_T("play bgm repeat"), NULL, 0, NULL);
				Playbgm = false;
			}

			DWORD frame_start_time = GetTickCount();
			while (peekmessage(&msg))
			{
				ChangeDirection(msg);
			}
			snakehead.move();
			snakebody.move(snakehead.GetLastPosX(), snakehead.GetLastPosY());
			if (CheckAlive())
			{
				fruit.Respawn();
				cleardevice();
				gamescene.draw_game_scene();

				FlushBatchDraw();
			}
			else
			{
				HWND hwnd = GetForegroundWindow();
				SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
				TCHAR message[100];
				mciSendString(_T("close bgm"), 0, 0, 0);
				
				if (cent > highest_score)
				{
					highest_score = cent;
					ScoreRecord = fopen("file/score_record.txt", "w");
					fprintf(ScoreRecord, "%d", highest_score);
					fclose(ScoreRecord);
					_stprintf_s(message, _T("Final score : %d\nMake a new record! God job!"), cent);
				}
				else
				{
					_stprintf_s(message, _T("Final score : %d\n%d scores until the highest score.\nNot bad, but please make more effort."), cent,highest_score - cent);
				}
				MessageBox(hwnd, message, _T("Game Over"), MB_OK);
				Reset = true;
				currentscene = Scene::MainMenu;
			}

			DWORD frame_end_time = GetTickCount();
			DWORD frame_delta_time = frame_end_time - frame_start_time;
			if (frame_delta_time < 1000 / FPS)
			{
				Sleep(1000 / FPS - frame_delta_time);
			}
			break;
		}
	}

	
	EndBatchDraw();

	return 0;
}



void ChangeDirection(ExMessage& msg)
{
		if (msg.message == WM_KEYDOWN)
		{
			switch (msg.vkcode)
			{
			case VK_UP:
				snakehead.ChangeDirection(Head::Direction::Up);
				break;
			case VK_DOWN:
				snakehead.ChangeDirection(Head::Direction::Down);
				break;
			case VK_RIGHT:
				snakehead.ChangeDirection(Head::Direction::Right);
				break;
			case VK_LEFT:
				snakehead.ChangeDirection(Head::Direction::Left);
				break;
			case VK_ESCAPE:
				is_esc = true;
				break;
			case VK_F1:
				if (SpeedUp)
				{
					FPS += 10;
					SpeedUp = false;
					SpeeddDown = true;
					is_speeding = true;
				}
				break;
			case VK_F2:
				if (SpeeddDown)
				{
					FPS -= 10;
					SpeedUp = true;
					SpeeddDown = false;
					is_speeding = false;
				}
				break;
			default:
				break;
			}
		}
}

bool CheckAlive()
{
	if (snakehead.GetPosX() <= 0 || snakehead.GetPosX() > GameSceneSizeHorizental || snakehead.GetPosY() <= 0 || snakehead.GetPosY() > GameSceneSizeVirtical || snakebody.CollideHead() || is_esc)
	{
		is_esc = false;
		return false;
	}
	return true;
}

void TriggerButton(ExMessage& msg)
{
	switch (msg.message)
	{
	case WM_MOUSEMOVE:
		if (msg.x >= ButtonPositionX && msg.x <= ButtonPositionX + ButtonWidth && msg.y >= ButtonPositionY && msg.y <= ButtonPositionY + ButtonHeight)
		{
			currentbuttonstate = Button::Active;
		}
		else
		{
			currentbuttonstate = Button::Unactive;
		}
		if (msg.x >= ExitButtonPositionX && msg.x <= ExitButtonPositionX + ExitButtonWidth && msg.y >= ExitButtonPositionY && msg.y <= ExitButtonPositionY + ExitButtonHeight)
		{
			currentexitbuttonstate = Button::Active;
		}
		else
		{
			currentexitbuttonstate = Button::Unactive;
		}
		break;
	case WM_LBUTTONDOWN:
		if (msg.x >= ButtonPositionX && msg.x <= ButtonPositionX + ButtonWidth && msg.y >= ButtonPositionY && msg.y <= ButtonPositionY + ButtonHeight)
		{
			currentbuttonstate = Button::Active;
			currentscene = Scene::GameScene;
		}
		if (msg.x >= ExitButtonPositionX && msg.x <= ExitButtonPositionX + ExitButtonWidth && msg.y >= ExitButtonPositionY && msg.y <= ExitButtonPositionY + ExitButtonHeight)
		{
			currentexitbuttonstate = Button::Active;
			RunningState = false;
		}
		break;
	default:
		break;
	}
}

void DrawButton()
{
	switch (currentbuttonstate)
	{
	case Button::Unactive:
		putimage_alpha(ButtonPositionX, ButtonPositionY, &ButtonUnactive);
		break;
	case Button::Active:
		putimage_alpha(ButtonPositionX, ButtonPositionY, &ButtonActive);
		break;
	default:
		break;
	}

	switch (currentexitbuttonstate)
	{
	case Button::Unactive:
		putimage_alpha(ExitButtonPositionX, ExitButtonPositionY, &ExitButtonUnactive);
		break;
	case Button::Active:
		putimage_alpha(ExitButtonPositionX, ExitButtonPositionY, &ExitButtonActive);
		break;
	default:
		break;
	}
}

void ResetGame()
{
	snakehead.Reset();
	snakebody.Reset();
	fruit.Reset();
	cent = 0;
	FPS = 10;
	mciSendString(_T("open music/bgm.mp3 alias bgm"), NULL, 0, NULL);
	Playbgm = true;
	SpeedUp = true;
	SpeeddDown = false;
	is_speeding = false;
}

int ReadScore()
{
	ScoreRecord = fopen("file/score_record.txt", "r");
	char ch;
	int score = 0;
	while ((ch = fgetc(ScoreRecord)) != EOF)
	{
		score = score * 10 + (ch - 48);
	}
	fclose(ScoreRecord);
	return score;
}